import { Graph, GraphEdge, GraphNode } from "./Graph"
import { Token } from "./Token"

export enum TokenType {
    IDF, NUM, CEQ, LEQ, LES, NEQ, GEQ, GTR, 
    BGN, END, IF, THN, ELS, CON, PRO, VAR, DO, WHL, CAL, RED, WRI, ODD, RPT, UTL,   // 保留字列表
    EQL, ADD, SUB, MUL, DIV, CMA, SEM, POI, LBR, RBR
}

export const keyword = [
    'begin',
    'end',
    'if',
    'then',
    'else',
    'const',
    'procedure',
    'var',
    'do',
    'while',
    'call',
    'read',
    'write',
    'odd',
    'repeat',
    'until'
]

export const operator = [
    '=',
    '+',
    '-',
    '*',
    '/',
    ',',
    ';',
    '.',
    '(',
    ')',
]

export const ptns = {
    space:      /\s/,  
    number:     /\d/, 
    letter:     /[a-zA-Z]/,
    literal:    /\w/,
    colon:      /:/,
    less:       /</,
    greater:    />/,
    equal:      /=/,
    operator:   /[+\-\*/().=,;]/,
    other:      null! 
}
/**
 * Graph<string!, RegExp>
 * 识别文字的DFA
 */
export const DFA = new Graph([
    // 0: /^[ ]$/ -> 0; letter -> 1; number -> 
    new GraphNode([
        // new GraphEdge(0, ptns.space),
        new GraphEdge(1, ptns.letter),
        new GraphEdge(2, ptns.number),
        new GraphEdge(3, ptns.colon),
        new GraphEdge(5, ptns.less),
        new GraphEdge(8, ptns.greater),
        new GraphEdge(10, ptns.operator),
    ], null),
    // 1: literal -> 1; number -> 
    new GraphNode([
        new GraphEdge(1, ptns.literal)
    ], TokenType.IDF),
    // 2: number -> 2; end -> NUM
    new GraphNode([
        new GraphEdge(2, ptns.number),
    ], TokenType.NUM),
    // 3: = -> 4
    new GraphNode([
        new GraphEdge(4, ptns.equal)
    ], null),
    // 4: end => CEQ
    new GraphNode([], TokenType.CEQ),
    // 5: = -> 6; > -> 7
    new GraphNode([
        new GraphEdge(6, ptns.equal),
        new GraphEdge(7, ptns.greater)
    ], TokenType.LES),
    // 6: end => LEQ(Less or EQual)
    new GraphNode([], TokenType.LEQ),
    // 7: end => NEQ(Not EQual)
    new GraphNode([], TokenType.NEQ),
    // 8: = -> 9; end => GTR(GreaTeR)
    new GraphNode([
        new GraphEdge(9, ptns.equal),
    ], TokenType.GTR),
    // 9: end => GEQ(Greater or EQual)
    new GraphNode([], TokenType.GEQ),
    // 10: end => OP(operator)
    new GraphNode([], TokenType.EQL)
])

export class PL0SyntaxError extends Error {
    static raise(token: Token | undefined, type: number, value: any = '') {
        const desc = [
            `不期望的字符 ${value}`,
            `结尾处缺少字符 ${value}`,
            `声明缺少 ${value}`,
            `常量声明未初始化`,
            `表达式不正确`,
            `子程序声明缺少 ${value}`,
            `子程序结尾缺少 ${value}`,
            `语句未赋值`,
            `不期望的符号 ${value}`,
            `读取/写入后未出现 ${value}`,
            `语句结尾处缺少字符 ${value}`,
            `条件句缺少字符 ${value}`,
            `循环语句缺少单词 ${value}`,
            `调用语句缺少标识符`,
            `未找到条件标识符`,
        ]
        return new PL0SyntaxError(token ? desc[type] + `，而得到${token.value}` : desc[type])
    }
    type: number = 0
    value: string = ''

    constructor(msg: string) {
        super(msg)
    }
}

export class PL0SemanticError extends Error {
    static raise(type: number, value: any = '') {
        const desc = [
            `标识符 ${value} 不存在或类型错误`,
            `子语句 ${value} 声明重复`,
            `常量 ${value} 声明重复`,
            `变量 ${value} 声明重复`
        ]
        return new PL0SemanticError(desc[type])
    }
    type: number = 0
    value: string = ''
    /**
     *
     */
    constructor(msg: string) {
        super(msg)
    }
}